package sk.stu.fei.tomsteam;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.io.IOException;
import javax.swing.JTextArea;
import org.snmp4j.*;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.security.Priv3DES;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.TransportIpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.AbstractTransportMapping;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

public class TrapReceiver implements CommandResponder, Runnable {
	   private String targetSnmpAgentURL;
	   private int targetSnmpAgentPort;
	   private JTextArea outConsole;

	   public TrapReceiver() {
	   } 

	   public TrapReceiver(JTextArea outConsole) {
	       this.outConsole = outConsole;
	   }


	   public TrapReceiver(JTextArea outConsole, String targetSnmpAgentURL, int  targetSnmpAgentPort) {
	       this.targetSnmpAgentURL = targetSnmpAgentURL;
	       this.targetSnmpAgentPort = targetSnmpAgentPort;
	       this.outConsole = outConsole;

	       /*try {
	           listen(new UdpAddress(targetSnmpAgentURL + "/" + targetSnmpAgentPort));
	       } catch (IOException e) {
	           e.printStackTrace();
	       }*/
	    }

	    public final synchronized void listen(TransportIpAddress address) throws IOException {


	        AbstractTransportMapping transport;
	        if (address instanceof TcpAddress) {
	            transport = new DefaultTcpTransportMapping((TcpAddress) address);
	        } else {
	            transport = new DefaultUdpTransportMapping((UdpAddress) address);
	        }

	        ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
	        MessageDispatcher mDispathcher = new MultiThreadedMessageDispatcher(
	            threadPool, new MessageDispatcherImpl());

	        // add message processing models
	        mDispathcher.addMessageProcessingModel(new MPv1());
	       mDispathcher.addMessageProcessingModel(new MPv2c());

	        // add all security protocols
	        SecurityProtocols.getInstance().addDefaultProtocols();
	        SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());

	        // Create Target
	        CommunityTarget target = new CommunityTarget();
	        target.setCommunity(new OctetString("public"));

	        Snmp snmp = new Snmp(mDispathcher, transport);
	        snmp.addCommandResponder(this);

	        transport.listen();
	        //System.out.println("Listening on " + address);

	        try {
	           this.wait();
	        } catch (InterruptedException ex) {
	           Thread.currentThread().interrupt();
	        }
	        }

	    /**
	    * This method will be called whenever a pdu is received on the given port
	    * specified in the listen() method.
	    * It is implementation of processPdu() method in CommandResponder
	    * interface.
	    */
	    @Override
	    public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {
	        //System.out.println("Received PDU...");
	        outConsole.append("Received trap [" + getDateTime() + "]\n");
	        PDU pdu = cmdRespEvent.getPDU();

	        if (pdu != null) {
	        	outConsole.append(pdu.toString() + "\n");
		        //outConsole.append("Trap Type = " + pdu.getType() + "\n");
		        //outConsole.append("Alarm Type: " + pdu.getVariableBindings().get(4) + "\n");
		        //outConsole.append("Alarm Message:  " + pdu.getVariableBindings().get(9) +  "\n\n");

	        }
	    }
	    
	    private String getDateTime() {
	    	long millis = System.currentTimeMillis();
	    	SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy, HH:mm:ss");
	    	Date date = new Date(millis);
	    	return sdf.format(date);
	    }
	    
	    
	     @Override
	     public void run() {
	        try {
	        	outConsole.append("Listening for incoming SNMP traps\n");
	            listen(new UdpAddress(targetSnmpAgentURL + "/" + targetSnmpAgentPort));
	        } catch (IOException e) {
	            outConsole.append("\nError occured while listening to SNMP messages: \n" + e.getMessage() + "\n\n");
	        }
	     }
}
